Had some time to add more features to my libvirt backup utility, now it
supports:
backing up virtual domains UEFI bios, initrd and kernel images if
defined.
virtnbdmap now uses the nbdkit COW plugin to map the backups as regular
NBD device. This allows users to replay complete backup chains
(full+inc/diff) to recover single files. Also makes the mapped device
writable, as such one can directly boot the virtual machine from the backup
images.
Check out my last article on that
topic or watch it in action.
As a side note: still there s an RFP open,
if one is interested in maintaining, as i find myself not having a valid
key in the keyring.. laziness.
Had some time to add more features to my libvirt backup utility, now it
supports:
Added backup mode differencial.
Save virtual domains UEFI bios, initrd and kernel images if defined.
virtnbdmap now uses the nbdkit COW plugin to map the backups as regular
NBD device. This allows users to replay complete backup chains
(full+inc/diff) to recover single files. As the resulting device is
writable, one can directly boot the virtual machine from the backup
images.
Check out my last article on that
topic or watch it in action.
Also, the dirty bitmap (incremental backup) feature now seems to be enabled by
default as of newer qemu and libvirt (8.2.x) versions.
As a side note: still there s an RFP open,
if one is interested in maintaining, as i find myself not having a valid
key in the keyring.. laziness.
I have some concerns about Matrix (the protocol, not the movie that
came out recently, although I do have concerns about that as
well). I've been watching the project for a long time, and it seems
more a promising alternative to many protocols like IRC, XMPP, and
Signal.
This review may sound a bit negative, because it focuses on those
concerns. I am the operator of an IRC network and people keep asking
me to bridge it with Matrix. I have myself considered just giving up
on IRC and converting to Matrix. This space is a living document
exploring my research of that problem space. The TL;DR: is that no,
I'm not setting up a bridge just yet, and I'm still on IRC.
This article was written over the course of the last three months, but
I have been watching the Matrix project for years (my logs seem to say
2016 at least). The article is rather long. It will likely take you
half an hour to read, so copy this over to your ebook reader,
your tablet, or dead trees, and lean back and relax as I show you
around the Matrix. Or, alternatively, just jump to a section that
interest you, most likely the conclusion.
Introduction to Matrix
Matrix is an "open standard for interoperable, decentralised,
real-time communication over IP. It can be used to power Instant
Messaging, VoIP/WebRTC signalling, Internet of Things communication -
or anywhere you need a standard HTTP API for publishing and
subscribing to data whilst tracking the conversation history".
It's also (when compared with XMPP) "an eventually consistent
global JSON database with an HTTP API and pubsub semantics - whilst
XMPP can be thought of as a message passing protocol."
According to their FAQ, the project started in 2014, has about
20,000 servers, and millions of users. Matrix works over HTTPS but
over a special port: 8448.
Security and privacy
I have some concerns about the security promises of Matrix. It's
advertised as a "secure" with "E2E [end-to-end] encryption", but how
does it actually work?
Data retention defaults
One of my main concerns with Matrix is data retention, which is a key
part of security in a threat model where (for example) an hostile
state actor wants to surveil your communications and can seize your
devices.
On IRC, servers don't actually keep messages all that long: they pass
them along to other servers and clients as fast as they can, only keep
them in memory, and move on to the next message. There are no concerns
about data retention on messages (and their metadata) other than the
network layer. (I'm ignoring the issues with user registration, which
is a separate, if valid, concern.) Obviously, an hostile server
could log everything passing through it, but IRC federations are
normally tightly controlled. So, if you trust your IRC operators, you
should be fairly safe. Obviously, clients can (and often do, even if
OTR is configured!) log all messages, but this is generally not
the default. Irssi, for example, does not log by
default. IRC bouncers are more likely to log to disk, of course,
to be able to do what they do.
Compare this to Matrix: when you send a message to a Matrix
homeserver, that server first stores it in its internal SQL
database. Then it will transmit that message to all clients connected
to that server and room, and to all other servers that have clients
connected to that room. Those remote servers, in turn, will keep a
copy of that message and all its metadata in their own database, by
default forever. On encrypted rooms those messages are encrypted, but
not their metadata.
There is a mechanism to expire entries in Synapse, but it is not
enabled by default. So one should generally assume that a message
sent on Matrix is never expired.
GDPR in the federation
But even if that setting was enabled by default, how do you control
it? This is a fundamental problem of the federation: if any user is
allowed to join a room (which is the default), those user's servers
will log all content and metadata from that room. That includes
private, one-on-one conversations, since those are essentially rooms
as well.
In the context of the GDPR, this is really tricky: who is the
responsible party (known as the "data controller") here? It's
basically any yahoo who fires up a home server and joins a room.
In a federated network, one has to wonder whether GDPR enforcement is
even possible at all. But in Matrix in particular, if you want to
enforce your right to be forgotten in a given room, you would have to:
enumerate all the users that ever joined the room while you were
there
discover all their home servers
start a GDPR procedure against all those servers
I recognize this is a hard problem to solve while still keeping an
open ecosystem. But I believe that Matrix should have much stricter
defaults towards data retention than right now. Message expiry should
be enforced by default, for example. (Note that there are also
redaction policies that could be used to implement part of the GDPR
automatically, see the privacy policy discussion below on that.)
Also keep in mind that, in the brave new peer-to-peer world that
Matrix is heading towards, the boundary between server and client is
likely to be fuzzier, which would make applying the GDPR even more difficult.
Update: this comment links to this post (in german) which
apparently studied the question and concluded that Matrix is not
GDPR-compliant.
In fact, maybe Synapse should be designed so that there's no
configurable flag to turn off data retention. A bit like how most
system loggers in UNIX (e.g. syslog) come with a log retention system
that typically rotate logs after a few weeks or month. Historically,
this was designed to keep hard drives from filling up, but it also has
the added benefit of limiting the amount of personal information kept
on disk in this modern day. (Arguably, syslog doesn't rotate logs on
its own, but, say, Debian GNU/Linux, as an installed system, does have
log retention policies well defined for installed packages, and those
can be discussed. And "no expiry" is definitely a bug.
We currently use cookies to support our use of Google Analytics on
the Website and Service. Google Analytics collects information about
how you use the Website and Service.
[...]
This helps us to provide you with a good experience when you
browse our Website and use our Service and also allows us to improve
our Website and our Service.
When I asked Matrix people about why they were using Google Analytics,
they explained this was for development purposes and they were aiming
for velocity at the time, not privacy (paraphrasing here).
They also included a "free to snitch" clause:
If we are or believe that we are under a duty to disclose or share
your personal data, we will do so in order to comply with any legal
obligation, the instructions or requests of a governmental authority
or regulator, including those outside of the UK.
Those are really broad terms, above and beyond what is typically
expected legally.
Like the current retention policies, such user tracking and
... "liberal" collaboration practices with the state set a bad
precedent for other home servers.
Thankfully, since the above policy was published (2017), the GDPR was
"implemented" (2018) and it seems like both the Element.io
privacy policy and the Matrix.org privacy policy have been
somewhat improved since.
Notable points of the new privacy policies:
2.3.1.1: the "federation" section actually outlines that
"Federated homeservers and Matrix clients which respect the Matrix
protocol are expected to honour these controls and
redaction/erasure requests, but other federated homeservers are
outside of the span of control of Element, and we cannot guarantee
how this data will be processed"
2.6: users under the age of 16 should not use the
matrix.org service
2.10: Upcloud, Mythic Beast, Amazon, and CloudFlare possibly
have access to your data (it's nice to at least mention this in the
privacy policy: many providers don't even bother admitting to this
kind of delegation)
I'm not super happy with all the trackers they have on the Element
platform, but then again you don't have to use that service. Your
favorite homeserver (assuming you are not on Matrix.org) probably has
their own Element deployment, hopefully without all that garbage.
Overall, this is all a huge improvement over the previous privacy
policy, so hats off to the Matrix people for figuring out a reasonable
policy in such a tricky context. I particularly like this bit:
We will forget your copy of your data upon your request. We will
also forward your request to be forgotten onto federated
homeservers. However - these homeservers are outside our span of
control, so we cannot guarantee they will forget your data.
It's great they implemented those mechanisms and, after all, if
there's an hostile party in there, nothing can prevent them from using
screenshots to just exfiltrate your data away from the client side
anyways, even with services typically seen as more secure, like
Signal.
As an aside, I also appreciate that Matrix.org has a fairly decent
code of conduct, based on the TODO CoC which checks all the
boxes in the geekfeminism wiki.
Metadata handling
Overall, privacy protections in Matrix mostly concern message
contents, not metadata. In other words, who's talking with who, when
and from where is not well protected. Compared to a tool like Signal,
which goes through great lengths to anonymize that data with features
like private contact discovery, disappearing messages,
sealed senders, and private groups, Matrix is definitely
behind. (Note: there is an issue open about message lifetimes in
Element since 2020, but it's not at even at the MSC stage yet.)
This is a known issue (opened in 2019) in Synapse, but this is
not just an implementation issue, it's a flaw in the protocol
itself. Home servers keep join/leave of all rooms, which gives clear
text information about who is talking to. Synapse logs may also
contain privately identifiable information that home server admins
might not be aware of in the first place. Those log rotation policies
are separate from the server-level retention policy, which may be
confusing for a novice sysadmin.
Combine this with the federation: even if you trust your home server
to do the right thing, the second you join a public room with
third-party home servers, those ideas kind of get thrown out because
those servers can do whatever they want with that information. Again,
a problem that is hard to solve in any federation.
To be fair, IRC doesn't have a great story here either: any client
knows not only who's talking to who in a room, but also typically
their client IP address. Servers can (and often do) obfuscate
this, but often that obfuscation is trivial to reverse. Some servers
do provide "cloaks" (sometimes automatically), but that's kind of a
"slap-on" solution that actually moves the problem elsewhere: now the
server knows a little more about the user.
Overall, I would worry much more about a Matrix home server seizure
than a IRC or Signal server seizure. Signal does get subpoenas,
and they can only give out a tiny bit of information about their
users: their phone number, and their registration, and last connection
date. Matrix carries a lot more information in its database.
Amplification attacks on URL previews
I (still!) run an Icecast server and sometimes share links to it
on IRC which, obviously, also ends up on (more than one!) Matrix home
servers because some people connect to IRC using Matrix. This, in
turn, means that Matrix will connect to that URL to generate a link
preview.
I feel this outlines a security issue, especially because those
sockets would be kept open seemingly forever. I tried to warn the
Matrix security team but somehow, I don't think this issue was taken
very seriously. Here's the disclosure timeline:
the bug was publicly disclosed in September 2020, and not
considered a security issue until I notified them, and even then,
I had to insist
no clear disclosure policy timeline was proposed or seems
established in the project (there is a security disclosure
policy but it doesn't include any predefined timeline)
I wasn't informed of the disclosure
the actual solution is a size limit (10MB, already implemented), a
time limit (30 seconds, implemented in PR 11784), and a
content type allow list (HTML, "media" or JSON, implemented in PR
11936), and I'm not sure it's adequate
(pure vanity:) I did not make it to their Hall of fame
I'm not sure those solutions are adequate because they all seem to
assume a single home server will pull that one URL for a little while
then stop. But in a federated network, many (possibly thousands)
home servers may be connected in a single room at once. If an attacker
drops a link into such a room, all those servers would connect to
that link all at once. This is an amplification attack: a small
amount of traffic will generate a lot more traffic to a single
target. It doesn't matter there are size or time limits: the
amplification is what matters here.
It should also be noted that clients that generate link previews
have more amplification because they are more numerous than
servers. And of course, the default Matrix client (Element) does
generate link previews as well.
That said, this is possibly not a problem specific to Matrix: any
federated service that generates link previews may suffer from this.
I'm honestly not sure what the solution is here. Maybe moderation?
Maybe link previews are just evil? All I know is there was this weird
bug in my Icecast server and I tried to ring the bell about it, and it
feels it was swept under the rug. Somehow I feel this is bound to blow
up again in the future, even with the current mitigation.
Moderation
In Matrix like elsewhere, Moderation is a hard problem. There is a
detailed moderation guide and much of this problem space is
actively worked on in Matrix right now. A fundamental problem with
moderating a federated space is that a user banned from a room can
rejoin the room from another server. This is why spam is such a
problem in Email, and why IRC networks have stopped federating ages
ago (see the IRC history for that fascinating story).
The mjolnir bot
The mjolnir moderation bot is designed to help with some of those
things. It can kick and ban users, redact all of a user's message (as
opposed to one by one), all of this across multiple rooms. It can also
subscribe to a federated block list published by matrix.org to block
known abusers (users or servers). Bans are pretty flexible and
can operate at the user, room, or server level.
Matrix people suggest making the bot admin of your channels, because
you can't take back admin from a user once given.
The command-line tool
There's also a new command line tool designed to do things like:
System notify users (all users/users from a list, specific user)
delete sessions/devices not seen for X days
purge the remote media cache
select rooms with various criteria (external/local/empty/created by/encrypted/cleartext)
purge history of theses rooms
shutdown rooms
This tool and Mjolnir are based on the admin API built into
Synapse.
Rate limiting
Synapse has pretty good built-in rate-limiting which blocks
repeated login, registration, joining, or messaging attempts. It may
also end up throttling servers on the federation based on those
settings.
Fundamental federation problems
Because users joining a room may come from another server, room
moderators are at the mercy of the registration and moderation
policies of those servers. Matrix is like IRC's +R mode ("only
registered users can join") by default, except that anyone can
register their own homeserver, which makes this limited.
Server admins can block IP addresses and home servers, but those tools
are not easily available to room admins. There is an API
(m.room.server_acl in /devtools) but it is not reliable
(thanks Austin Huang for the clarification).
Matrix has the concept of guest accounts, but it is not used very
much, and virtually no client or homeserver supports it. This contrasts with the way
IRC works: by default, anyone can join an IRC network even without
authentication. Some channels require registration, but in general you
are free to join and look around (until you get blocked, of course).
I have seen anecdotal evidence (CW: Twitter, nitter link) that "moderating bridges is hell", and
I can imagine why. Moderation is already hard enough on one
federation, when you bridge a room with another network, you inherit
all the problems from that network but without the entire abuse
control tools from the original network's API...
Room admins
Matrix, in particular, has the problem that room administrators (which
have the power to redact messages, ban users, and promote other users)
are bound to their Matrix ID which is, in turn, bound to their home
servers. This implies that a home server administrators could (1)
impersonate a given user and (2) use that to hijack the room. So in
practice, the home server is the trust anchor for rooms, not the user
themselves.
That said, if server B administrator hijack user joe on server B,
they will hijack that room on that specific server. This will not
(necessarily) affect users on the other servers, as servers could
refuse parts of the updates or ban the compromised account (or
server).
It does seem like a major flaw that room credentials are bound to
Matrix identifiers, as opposed to the E2E encryption credentials. In
an encrypted room even with fully verified members, a compromised or
hostile home server can still take over the room by impersonating an
admin. That admin (or even a newly minted user) can then send events
or listen on the conversations.
This is even more frustrating when you consider that Matrix events are
actually signed and therefore have some authentication attached
to them, acting like some sort of Merkle tree (as it contains a link
to previous events). That signature, however, is made from the
homeserver PKI keys, not the client's E2E keys, which makes E2E feel
like it has been "bolted on" later.
Availability
While Matrix has a strong advantage over Signal in that it's
decentralized (so anyone can run their own homeserver,), I couldn't
find an easy way to run a "multi-primary" setup, or even a "redundant"
setup (even if with a single primary backend), short of going full-on
"replicate PostgreSQL and Redis data", which is not typically for the
faint of heart.
How this works in IRC
On IRC, it's quite easy to setup redundant nodes. All you need is:
a new machine (with it's own public address with an open port)
a shared secret (or certificate) between that machine and an
existing one on the network
a connect block on both servers
That's it: the node will join the network and people can connect to it
as usual and share the same user/namespace as the rest of the
network. The servers take care of synchronizing state: you do not need
to worry about replicating a database server.
(Now, experienced IRC people will know there's a catch here: IRC
doesn't have authentication built in, and relies on "services" which
are basically bots that authenticate users (I'm simplifying, don't
nitpick). If that service goes down, the network still works, but
then people can't authenticate, and they can start doing nasty things
like steal people's identity if they get knocked offline. But still:
basic functionality still works: you can talk in rooms and with users
that are on the reachable network.)
User identities
Matrix is more complicated. Each "home server" has its own identity
namespace: a specific user (say @anarcat:matrix.org) is bound to
that specific home server. If that server goes down, that user is
completely disconnected. They could register a new account elsewhere
and reconnect, but then they basically lose all their configuration:
contacts, joined channels are all lost.
(Also notice how the Matrix IDs don't look like a typical user address
like an email in XMPP. They at least did their homework and got the
allocation for the scheme.)
Rooms
Users talk to each other in "rooms", even in one-to-one
communications. (Rooms are also used for other things like "spaces",
they're basically used for everything, think "everything is a file"
kind of tool.) For rooms, home servers act more like IRC nodes in that
they keep a local state of the chat room and synchronize it with other
servers. Users can keep talking inside a room if the server that
originally hosts the room goes down. Rooms can have a local,
server-specific "alias" so that, say, #room:matrix.org is also
visible as #room:example.com on the example.com home server. Both
addresses refer to the same room underlying room.
(Finding this in the Element settings is not obvious though, because
that "alias" are actually called a "local address" there. So to create
such an alias (in Element), you need to go in the room settings'
"General" section, "Show more" in "Local address", then add the alias
name (e.g. foo), and then that room will be available on your
example.com homeserver as #foo:example.com.)
So a room doesn't belong to a server, it belongs to the federation,
and anyone can join the room from any serer (if the room is public, or
if invited otherwise). You can create a room on server A and when a
user from server B joins, the room will be replicated on server B as
well. If server A fails, server B will keep relaying traffic to
connected users and servers.
A room is therefore not fundamentally addressed with the above alias,
instead ,it has a internal Matrix ID, which basically a random
string. It has a server name attached to it, but that was made just to
avoid collisions. That can get a little confusing. For example, the
#fractal:gnome.org room is an alias on the gnome.org server, but
the room ID is !hwiGbsdSTZIwSRfybq:matrix.org. That's because the
room was created on matrix.org, but the preferred branding is
gnome.org now.
As an aside, rooms, by default, live forever, even after the last user
quits. There's an admin API to delete rooms and a tombstone
event to redirect to another one, but neither have a GUI yet. The
latter is part of MSC1501 ("Room version upgrades") which allows
a room admin to close a room, with a message and a pointer to another
room.
Spaces
Discovering rooms can be tricky: there is a per-server room
directory, but Matrix.org people are trying to deprecate it in favor
of "Spaces". Room directories were ripe for abuse: anyone can create a
room, so anyone can show up in there. It's possible to restrict who
can add aliases, but anyways directories were seen as too limited.
In contrast, a "Space" is basically a room that's an index of other
rooms (including other spaces), so existing moderation and
administration mechanism that work in rooms can (somewhat) work in
spaces as well. This enables a room directory that works across
federation, regardless on which server they were originally created.
New users can be added to a space or room automatically in
Synapse. (Existing users can be told about the space with a server
notice.) This gives admins a way to pre-populate a list of rooms on a
server, which is useful to build clusters of related home servers,
providing some sort of redundancy, at the room -- not user -- level.
Home servers
So while you can workaround a home server going down at the room
level, there's no such thing at the home server level, for user
identities. So if you want those identities to be stable in the long
term, you need to think about high availability. One limitation is
that the domain name (e.g. matrix.example.com) must never change in
the future, as renaming home servers is not supported.
The documentation used to say you could "run a hot spare" but that has
been removed. Last I heard, it was not possible to run a
high-availability setup where multiple, separate locations could
replace each other automatically. You can have high performance
setups where the load gets distributed among workers, but those
are based on a shared database (Redis and PostgreSQL) backend.
So my guess is it would be possible to create a "warm" spare server of
a matrix home server with regular PostgreSQL replication, but
that is not documented in the Synapse manual. This sort of setup
would also not be useful to deal with networking issues or denial of
service attacks, as you will not be able to spread the load over
multiple network locations easily. Redis and PostgreSQL heroes are
welcome to provide their multi-primary solution in the comments. In
the meantime, I'll just point out this is a solution that's handled
somewhat more gracefully in IRC, by having the possibility of
delegating the authentication layer.
Delegations
If you do not want to run a Matrix server yourself, it's possible to
delegate the entire thing to another server. There's a server
discovery API which uses the .well-known pattern (or SRV
records, but that's "not recommended" and a bit confusing) to
delegate that service to another server. Be warned that the server
still needs to be explicitly configured for your domain. You can't
just put:
"m.server": "matrix.org:443"
... on https://example.com/.well-known/matrix/server and start using
@you:example.com as a Matrix ID. That's because Matrix doesn't
support "virtual hosting" and you'd still be connecting to rooms and
people with your matrix.org identity, not example.com as you would
normally expect. This is also why you cannot rename your home
server.
The server discovery API is what allows servers to find each
other. Clients, on the other hand, use the client-server discovery
API: this is what allows a given client to find your home server
when you type your Matrix ID on login.
Performance
The high availability discussion brushed over the performance of
Matrix itself, but let's now dig into that.
Horizontal scalability
There were serious scalability issues of the main Matrix server,
Synapse, in the past. So the Matrix team has been working hard to
improve its design. Since Synapse 1.22 the home server can
horizontally scale to multiple workers (see this blog post for details)
which can make it easier to scale large servers.
Other implementations
There are other promising home servers implementations from a
performance standpoint (dendrite, Golang, entered beta in late
2020; conduit, Rust, beta; others), but none of those
are feature-complete so there's a trade-off to be made there. Synapse
is also adding a lot of feature fast, so it's an open question whether
the others will ever catch up. (I have heard that Dendrite might
actually surpass Synapse in features within a few years, which would
put Synapse in a more "LTS" situation.)
Latency
Matrix can feel slow sometimes. For example, joining the "Matrix HQ"
room in Element (from matrix.debian.social) takes a few minutes
and then fails. That is because the home server has to sync the
entire room state when you join the room. There was promising work on
this announced in the lengthy 2021 retrospective, and some of
that work landed (partial sync) in the 1.53 release already.
Other improvements coming include sliding sync, lazy loading
over federation, and fast room joins. So that's actually
something that could be fixed in the fairly short term.
But in general, communication in Matrix doesn't feel as "snappy" as on
IRC or even Signal. It's hard to quantify this without instrumenting a
full latency test bed (for example the tools I used in the terminal
emulators latency tests), but
even just typing in a web browser feels slower than typing in a xterm
or Emacs for me.
Even in conversations, I "feel" people don't immediately respond as
fast. In fact, this could be an interesting double-blind experiment to
make: have people guess whether they are talking to a person on
Matrix, XMPP, or IRC, for example. My theory would be that people
could notice that Matrix users are slower, if only because of the TCP
round-trip time each message has to take.
Matrix: "struggled to send and receive messages", joining a room
takes forever as it has to sync all history, "took 20-30 seconds
for my messages to be sent and another 20 seconds for further
responses"
XMPP: "worked in real-time, full encryption, with nearly zero
lag"
So that was interesting. I suspect IRC would have also fared better,
but that's just a feeling.
Other improvements to the transport layer include support for
websocket and the CoAP proxy work from 2019 (targeting
100bps links), but both seem stalled at the time of writing. The
Matrix people have also announced the pinecone p2p overlay
network which aims at solving large, internet-scale routing
problems. See also this talk at FOSDEM 2022.
Usability
Onboarding and workflow
The workflow for joining a room, when you use Element web, is not
great:
As you might have guessed by now, there is a specification to
solve this, but web browsers need to adopt it as well, so that's far
from actually being solved. At least browsers generally know about the
matrix: scheme, it's just not exactly clear what they should do with
it, especially when the handler is just another web page (e.g. Element
web).
In general, when compared with tools like Signal or WhatsApp, Matrix
doesn't fare so well in terms of user discovery. I probably have some
of my normal contacts that have a Matrix account as well, but there's
really no way to know. It's kind of creepy when Signal tells you
"this person is on Signal!" but it's also pretty cool that it works,
and they actually implemented it pretty well.
Registration is also less obvious: in Signal, the app confirms your
phone number automatically. It's friction-less and quick. In Matrix,
you need to learn about home servers, pick one, register (with a
password! aargh!), and then setup encryption keys (not default),
etc. It's a lot more friction.
And look, I understand: giving away your phone number is a huge
trade-off. I don't like it either. But it solves a real problem and
makes encryption accessible to a ton more people. Matrix does have
"identity servers" that can serve that purpose, but I don't feel
confident sharing my phone number there. It doesn't help that the
identity servers don't have private contact discovery: giving them
your phone number is a more serious security compromise than with
Signal.
There's a catch-22 here too: because no one feels like giving away
their phone numbers, no one does, and everyone assumes that stuff
doesn't work anyways. Like it or not, Signal forcing people to
divulge their phone number actually gives them critical mass that
means actually a lot of my relatives are on Signal and I don't have
to install crap like WhatsApp to talk with them.
5 minute clients evaluation
Throughout all my tests I evaluated a handful of Matrix clients,
mostly from Flathub because almost none of them are packaged in
Debian.
Right now I'm using Element, the flagship client from Matrix.org, in a
web browser window, with the PopUp Window extension. This makes
it look almost like a native app, and opens links in my main browser
window (instead of a new tab in that separate window), which is
nice. But I'm tired of buying memory to feed my web browser, so this
indirection has to stop. Furthermore, I'm often getting completely
logged off from Element, which means re-logging in, recovering my
security keys, and reconfiguring my settings. That is extremely
annoying.
Coming from Irssi, Element is really "GUI-y" (pronounced
"gooey"). Lots of clickety happening. To mark conversations as read,
in particular, I need to click-click-click on all the tabs that have
some activity. There's no "jump to latest message" or "mark all as
read" functionality as far as I could tell. In Irssi the former is
built-in (alt-a) and I made a custom /READ command for
the latter:
/ALIAS READ script exec \$_->activity(0) for Irssi::windows
And yes, that's a Perl script in my IRC client. I am not aware of any
Matrix client that does stuff like that, except maybe Weechat, if we
can call it a Matrix client, or Irssi itself, now that it has a
Matrix plugin (!).
As for other clients, I have looked through the Matrix Client
Matrix (confusing right?) to try to figure out which one to try,
and, even after selecting Linux as a filter, the chart is just too
wide to figure out anything. So I tried those, kind of randomly:
Fractal
Mirage
Nheko
Quaternion
Unfortunately, I lost my notes on those, I don't actually remember
which one did what. I still have a session open with Mirage, so I
guess that means it's the one I preferred, but I remember they were
also all very GUI-y.
Maybe I need to look at weechat-matrix or gomuks. At least Weechat
is scriptable so I could continue playing the power-user. Right now my
strategy with messaging (and that includes microblogging like Twitter
or Mastodon) is that everything goes through my IRC client, so Weechat
could actually fit well in there. Going with gomuks, on the other
hand, would mean running it in parallel with Irssi or ... ditching
IRC, which is a leap I'm not quite ready to take just yet.
Oh, and basically none of those clients (except Nheko and Element)
support VoIP, which is still kind of a second-class citizen in
Matrix. It does not support large multimedia rooms, for example:
Jitsi was used for FOSDEM instead of the native videoconferencing
system.
Bots
This falls a little aside the "usability" section, but I didn't know
where to put this... There's a few Matrix bots out there, and you are
likely going to be able to replace your existing bots with Matrix
bots. It's true that IRC has a long and impressive history with lots
of various bots doing various things, but given how young Matrix is,
there's still a good variety:
maubot: generic bot with tons of usual plugins like sed, dice,
karma, xkcd, echo, rss, reminder, translate, react, exec,
gitlab/github webhook receivers, weather, etc
opsdroid: framework to implement "chat ops" in Matrix,
connects with Matrix, GitHub, GitLab, Shell commands, Slack, etc
One thing I haven't found an equivalent for is Debian's
MeetBot. There's an archive bot but it doesn't have topics
or a meeting chair, or HTML logs.
Working on Matrix
As a developer, I find Matrix kind of intimidating. The specification
is huge. The official specification itself looks somewhat
digestable: it's only 6 APIs so that looks, at first, kind of
reasonable. But whenever you start asking complicated questions about
Matrix, you quickly fall into the Matrix Spec Change
specification (which, yes, is a separate specification). And there are
literally hundreds of MSCs flying around. It's hard to tell
what's been adopted and what hasn't, and even harder to figure out if
your specific client has implemented it.
(One trendy answer to this problem is to "rewrite it in rust": Matrix
are working on implementing a lot of those specifications in a
matrix-rust-sdk that's designed to take the implementation
details away from users.)
Just taking the latest weekly Matrix report, you find that
three new MSCs proposed, just last week! There's even a graph that
shows the number of MSCs is progressing steadily, at 600+ proposals
total, with the majority (300+) "new". I would guess the "merged" ones
are at about 150.
That's a lot of text which includes stuff like 3D worlds which,
frankly, I don't think you should be working on when you have such
important security and usability problems. (The internet as a whole,
arguably, doesn't fare much better. RFC600 is a really obscure
discussion about "INTERFACING AN ILLINOIS PLASMA TERMINAL TO THE
ARPANET". Maybe that's how many MSCs will end up as well, left
forgotten in the pits of history.)
And that's the thing: maybe the Matrix people have a different
objective than I have. They want to connect everything to everything,
and make Matrix a generic transport for all sorts of applications,
including virtual reality, collaborative editors, and so on.
I just want secure, simple messaging. Possibly with good file
transfers, and video calls. That it works with existing stuff is good,
and it should be federated to remove the "Signal point of
failure". So I'm a bit worried with the direction all those MSCs are
taking, especially when you consider that clients other than Element
are still struggling to keep up with basic features like end-to-end
encryption or room discovery, never mind voice or spaces...
Conclusion
Overall, Matrix is somehow in the space XMPP was a few years ago. It
has a ton of features, pretty good clients, and a large
community. It seems to have gained some of the momentum that XMPP has
lost. It may have the most potential to replace Signal if something
bad would happen to it (like, I don't know, getting banned or
going nuts with cryptocurrency)...
But it's really not there yet, and I don't see Matrix trying to get
there either, which is a bit worrisome.
Looking back at history
I'm also worried that we are repeating the errors of the past. The
history of federated services is really fascinating:. IRC, FTP, HTTP,
and SMTP were all created in the early days of the internet, and are
all still around (except, arguably, FTP, which was removed from major
browsers recently). All of them had to face serious challenges in
growing their federation.
IRC had numerous conflicts and forks, both at the technical level
but also at the political level. The history of IRC is really
something that anyone working on a federated system should study in
detail, because they are bound to make the same mistakes if they are
not familiar with it. The "short" version is:
1988: Finnish researcher publishes first IRC source code
1989: 40 servers worldwide, mostly universities
1990: EFnet ("eris-free network") fork which blocks the "open
relay", named Eris - followers of Eris form the A-net, which
promptly dissolves itself, with only EFnet remaining
1992: Undernet fork, which offered authentication ("services"),
routing improvements and timestamp-based channel synchronisation
1994: DALnet fork, from Undernet, again on a technical disagreement
1995: Freenode founded
1996: IRCnet forks from EFnet, following a flame war of historical
proportion, splitting the network between Europe and the Americas
1997: Quakenet founded
1999: (XMPP founded)
2001: 6 million users, OFTC founded
2002: DALnet peaks at 136,000 users
2003: IRC as a whole peaks at 10 million users, EFnet peaks at
141,000 users
2004: (Facebook founded), Undernet peaks at 159,000 users
2005: Quakenet peaks at 242,000 users, IRCnet peaks at 136,000
(Youtube founded)
2006: (Twitter founded)
2009: (WhatsApp, Pinterest founded)
2010: (TextSecure AKA Signal, Instagram founded)
2011: (Snapchat founded)
~2013: Freenode peaks at ~100,000 users
2016: IRCv3 standardisation effort started (TikTok founded)
2021: Freenode self-destructs, Libera chat founded
2022: Libera peaks at 50,000 users, OFTC peaks at 30,000 users
(The numbers were taken from the Wikipedia page and
Netsplit.de. Note that I also include other networks launch in
parenthesis for context.)
Pretty dramatic, don't you think? Eventually, somehow, IRC became
irrelevant for most people: few people are even aware of it now. With
less than a million users active, it's smaller than Mastodon, XMPP, or
Matrix at this point.1 If I were to venture a guess, I'd say that
infighting, lack of a standardization body, and a somewhat annoying
protocol meant the network could not grow. It's also possible that the
decentralised yet centralised structure of IRC networks limited their
reliability and growth.
But large social media companies have also taken over the space:
observe how IRC numbers peak around the time the wave of large social
media companies emerge, especially Facebook (2.9B users!!) and Twitter
(400M users).
Where the federated services are in history
Right now, Matrix, and Mastodon (and email!) are at the
"pre-EFnet" stage: anyone can join the federation. Mastodon has
started working on a global block list of fascist servers which is
interesting, but it's still an open federation. Right now, Matrix is
totally open, but matrix.org publishes a (federated) block list
of hostile servers (#matrix-org-coc-bl:matrix.org, yes, of course
it's a room).
Interestingly, Email is also in that stage, where there are block
lists of spammers, and it's a race between those blockers and
spammers. Large email providers, obviously, are getting closer to the
EFnet stage: you could consider they only accept email from themselves
or between themselves. It's getting increasingly hard to deliver mail
to Outlook and Gmail for example, partly because of bias against small
providers, but also because they are including more and more
machine-learning tools to sort through email and those systems are,
fundamentally, unknowable. It's not quite the same as splitting the
federation the way EFnet did, but the effect is similar.
HTTP has somehow managed to live in a parallel universe, as it's
technically still completely federated: anyone can start a web server
if they have a public IP address and anyone can connect to it. The
catch, of course, is how you find the darn thing. Which is how Google
became one of the most powerful corporations on earth, and how they
became the gatekeepers of human knowledge online.
I have only briefly mentioned XMPP here, and my XMPP fans will
undoubtedly comment on that, but I think it's somewhere in the middle
of all of this. It was co-opted by Facebook and Google, and
both corporations have abandoned it to its fate. I remember fondly the
days where I could do instant messaging with my contacts who had a
Gmail account. Those days are gone, and I don't talk to anyone over
Jabber anymore, unfortunately. And this is a threat that Matrix still
has to face.
It's also the threat Email is currently facing. On the one hand
corporations like Facebook want to completely destroy it and have
mostly succeeded: many people just have an email account to
register on things and talk to their friends over Instagram or
(lately) TikTok (which, I know, is not Facebook, but they started that
fire).
On the other hand, you have corporations like Microsoft and Google who
are still using and providing email services because, frankly, you
still do need email for stuff, just like fax is still around
but they are more and more isolated in their own silo. At this point,
it's only a matter of time they reach critical mass and just decide
that the risk of allowing external mail coming in is not worth the
cost. They'll simply flip the switch and work on an allow-list
principle. Then we'll have closed the loop and email will be
dead, just like IRC is "dead" now.
I wonder which path Matrix will take. Could it liberate us from these
vicious cycles?
Update: this generated some discussions on lobste.rs.
Notable omission from that list: Youtube, with its mind-boggling
2.6 billion users...
Those are not the kind of numbers you just "need to convince a
brother or sister" to grow the network...
What's in sid?
I wanted to check what version of libc was used in current Debian sid.
I am lazy and I used podman to check.
However I noticed that apt update is very slow for me, 20kB/s. Wondering if something is wrong.
I'm not a fan of BTRFS. This page serves as a reminder of why,
but also a cheat sheet to figure out basic tasks in a BTRFS
environment because those are not obvious to me, even after
repeatedly having to deal with them.
Content warning: there might be mentions of ZFS.
Stability concerns
I'm worried about BTRFS stability, which has been historically
... changing. RAID-5 and RAID-6 are still marked unstable, for
example. It's kind of a lucky guess whether your current kernel will
behave properly with your planned workload. For example, in Linux
4.9, RAID-1 and RAID-10 were marked as "mostly OK" with a note that
says:
Needs to be able to create two copies always. Can get stuck in
irreversible read-only mode if only one copy can be made.
Even as of now, RAID-1 and RAID-10 has this note:
The simple redundancy RAID levels utilize different mirrors in a way
that does not achieve the maximum performance. The logic can be
improved so the reads will spread over the mirrors evenly or based
on device congestion.
Granted, that's not a stability concern anymore, just performance. A
reviewer of a draft of this article actually claimed that BTRFS only
reads from one of the drives, which hopefully is inaccurate, but goes
to show how confusing all this is.
There are other warnings in the Debian wiki that are quite
scary. Even the legendary Arch wiki has a warning on top of their
BTRFS page, still.
Even if those issues are now fixed, it can be hard to tell when they
were fixed. There is a changelog by feature but it explicitly
warns that it doesn't know "which kernel version it is considered
mature enough for production use", so it's also useless for this.
It would have been much better if BTRFS was released into the world
only when those bugs were being completely fixed. Or that, at least,
features were announced when they were stable, not just "we merged to
mainline, good luck". Even now, we get mixed messages even in the
official BTRFS documentation which says "The Btrfs code base is
stable" (main page) while at the same time clearly stating
unstable parts in the status page (currently RAID56).
There are much harsher BTRFS critics than me out there so I
will stop here, but let's just say that I feel a little uncomfortable
trusting server data with full RAID arrays to BTRFS. But surely, for a
workstation, things should just work smoothly... Right? Well, let's
see the snags I hit.
My BTRFS test setup
Before I go any further, I should probably clarify how I am testing
BTRFS in the first place.
The reason I tried BTRFS is that I was ... let's just say "strongly
encouraged" by the LWN editors to install Fedora for the
terminal emulators series.
That, in turn, meant the setup was done with BTRFS, because that was
somewhat the default in Fedora 27 (or did I want to experiment? I
don't remember, it's been too long already).
So Fedora was setup on my 1TB HDD and, with encryption, the partition
table looks like this:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 931,5G 0 disk
sda1 8:1 0 200M 0 part /boot/efi
sda2 8:2 0 1G 0 part /boot
sda3 8:3 0 7,8G 0 part
fedora_swap 253:5 0 7.8G 0 crypt [SWAP]
sda4 8:4 0 922,5G 0 part
fedora_crypt 253:4 0 922,5G 0 crypt /
(This might not entirely be accurate: I rebuilt this from the Debian
side of things.)
This is pretty straightforward, except for the swap partition:
normally, I just treat swap like any other logical volume and create
it in a logical volume. This is now just speculation, but I bet it was
setup this way because "swap" support was only added in BTRFS 5.0.
I fully expect BTRFS experts to yell at me now because this is an old
setup and BTRFS is so much better now, but that's exactly the point
here. That setup is not that old (2018? old? really?), and migrating
to a new partition scheme isn't exactly practical right now. But let's
move on to more practical considerations.
No builtin encryption
BTRFS aims at replacing the entire mdadm, LVM, and ext4
stack with a single entity, and adding new features like
deduplication, checksums and so on.
Yet there is one feature it is critically missing: encryption. See, my
typical stack is actually mdadm, LUKS, and then LVM and
ext4. This is convenient because I have only a single volume to
decrypt.
If I were to use BTRFS on servers, I'd need to have one LUKS volume
per-disk. For a simple RAID-1 array, that's not too bad: one extra
key. But for large RAID-10 arrays, this gets really unwieldy.
The obvious BTRFS alternative, ZFS, supports encryption out of
the box and mixes it above the disks so you only have one passphrase
to enter. The main downside of ZFS encryption is that it happens above
the "pool" level so you can typically see filesystem names (and
possibly snapshots, depending on how it is built), which is not the
case with a more traditional stack.
Subvolumes, filesystems, and devices
I find BTRFS's architecture to be utterly confusing. In the
traditional LVM stack (which is itself kind of confusing if you're new
to that stuff), you have those layers:
disks: let's say /dev/nvme0n1 and nvme1n1
RAID arrays with mdadm: let's say the above disks are joined in a
RAID-1 array in /dev/md1
volume groups or VG with LVM: the above RAID device (technically a
"physical volume" or PV) is assigned into a VG, let's call it
vg_tbbuild05 (multiple PVs can be added to a single VG which is
why there is that abstraction)
LVM logical volumes: out of that volume group actually "virtual
partitions" or "logical volumes" are created, that is where your
filesystem lives
filesystem, typically with ext4: that's your normal filesystem,
which treats the logical volume as just another block device
I stripped the other nvme1n1 disk because it's basically the same.
Now, if we look at my BTRFS-enabled workstation, which doesn't even
have RAID, we have the following:
disk: /dev/sda with, again, /dev/sda4 being where BTRFS lives
filesystem: fedora_crypt, which is, confusingly, kind of like a
volume group. it's where everything lives. i think.
subvolumes: home, root, /, etc. those are actually the things
that get mounted. you'd think you'd mount a filesystem, but no, you
mount a subvolume. that is backwards.
It looks something like this to lsblk:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 931,5G 0 disk
sda1 8:1 0 200M 0 part /boot/efi
sda2 8:2 0 1G 0 part /boot
sda3 8:3 0 7,8G 0 part [SWAP]
sda4 8:4 0 922,5G 0 part
fedora_crypt 253:4 0 922,5G 0 crypt /srv
Notice how we don't see all the BTRFS volumes here? Maybe it's because
I'm mounting this from the Debian side, but lsblk definitely gets
confused here. I frankly don't quite understand what's going on, even
after repeatedly looking around the rather dismal
documentation. But that's what I gather from the following
commands:
root@curie:/home/anarcat# btrfs filesystem show
Label: 'fedora' uuid: 5abb9def-c725-44ef-a45e-d72657803f37
Total devices 1 FS bytes used 883.29GiB
devid 1 size 922.47GiB used 916.47GiB path /dev/mapper/fedora_crypt
root@curie:/home/anarcat# btrfs subvolume list /srv
ID 257 gen 108092 top level 5 path home
ID 258 gen 108094 top level 5 path root
ID 263 gen 108020 top level 258 path root/var/lib/machines
I only got to that point through trial and error. Notice how I use an
existing mountpoint to list the related subvolumes. If I try to use
the filesystem path, the one that's listed in filesystem show, I
fail:
root@curie:/home/anarcat# btrfs subvolume list /dev/mapper/fedora_crypt
ERROR: not a btrfs filesystem: /dev/mapper/fedora_crypt
ERROR: can't access '/dev/mapper/fedora_crypt'
Maybe I just need to use the label? Nope:
root@curie:/home/anarcat# btrfs subvolume list fedora
ERROR: cannot access 'fedora': No such file or directory
ERROR: can't access 'fedora'
This is really confusing. I don't even know if I understand this
right, and I've been staring at this all afternoon. Hopefully, the
lazyweb will correct me eventually.
(As an aside, why are they called "subvolumes"? If something is a
"sub" of "something else", that "something else" must exist
right? But no, BTRFS doesn't have "volumes", it only has
"subvolumes". Go figure. Presumably the filesystem still holds "files"
though, at least empirically it doesn't seem like it lost anything so
far.
In any case, at least I can refer to this section in the future, the
next time I fumble around the btrfs commandline, as I surely will. I
will possibly even update this section as I get better at it, or based
on my reader's judicious feedback.
Mounting BTRFS subvolumes
So how did I even get to that point? I have this in my /etc/fstab,
on the Debian side of things:
This thankfully ignores all the subvolume nonsense because it relies
on the UUID. mount tells me that's actually the "root" (? /?)
subvolume:
root@curie:/home/anarcat# mount grep /srv
/dev/mapper/fedora_crypt on /srv type btrfs (rw,relatime,space_cache,subvolid=5,subvol=/)
Let's see if I can mount the other volumes I have on there. Remember
that subvolume list showed I had home, root, and
var/lib/machines. Let's try root:
mount -o subvol=root /dev/mapper/fedora_crypt /mnt
Interestingly, root is not the same as /, it's a different
subvolume! It seems to be the Fedora root (/, really) filesystem. No
idea what is happening here. I also have a home subvolume, let's
mount it too, for good measure:
mount -o subvol=home /dev/mapper/fedora_crypt /mnt/home
Note that lsblk doesn't notice those two new mountpoints, and that's
normal: it only lists block devices and subvolumes (rather
inconveniently, I'd say) do not show up as devices:
root@curie:/home/anarcat# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 931,5G 0 disk
sda1 8:1 0 200M 0 part
sda2 8:2 0 1G 0 part
sda3 8:3 0 7,8G 0 part
sda4 8:4 0 922,5G 0 part
fedora_crypt 253:4 0 922,5G 0 crypt /srv
This is really, really confusing. Maybe I did something wrong in the
setup. Maybe it's because I'm mounting it from outside Fedora. Either
way, it just doesn't feel right.
No disk usage per volume
If you want to see what's taking up space in one of those subvolumes,
tough luck:
(Notice, in passing, that it looks like the same filesystem is mounted
in different places. In that sense, you'd expect /srv and /mnt
(and /mnt/home?!) to be exactly the same, but no: they are entirely
different directory structures, which I will not call "filesystems"
here because everyone's head will explode in sparks of confusion.)
Yes, disk space is shared (that's the Size and Avail columns,
makes sense). But nope, no cookie for you: they all have the same
Used columns, so you need to actually walk the entire filesystem to
figure out what each disk takes.
(For future reference, that's basically:
root@curie:/home/anarcat# time du -schx /mnt/home /mnt /srv
124M /mnt/home
7.5G /mnt
875G /srv
883G total
real 2m49.080s
user 0m3.664s
sys 0m19.013s
And yes, that was painfully slow.)
ZFS actually has some oddities in that regard, but at least it tells
me how much disk each volume (and snapshot) takes:
That's 56360 times faster, by the way.
But yes, that's not fair: those in the know will know there's a
different command to do what df does with BTRFS filesystems, the
btrfs filesystem usage command:
Almost as fast as ZFS's df! Good job. But wait. That doesn't actually
tell me usage per subvolume. Notice it's filesystem usage, not
subvolume usage, which unhelpfully refuses to exist. That command
only shows that one "filesystem" internal statistics that are pretty
opaque.. You can also appreciate that it's wasting 6GB of
"unallocated" disk space there: I probably did something Very Wrong
and should be punished by Hacker News. I also wonder why it has 1.68GB
of "metadata" used...
At this point, I just really want to throw that thing out of the
window and restart from scratch. I don't really feel like learning the
BTRFS internals, as they seem oblique and completely bizarre to me. It
feels a little like the state of PHP now: it's actually pretty solid,
but built upon so many layers of cruft that I still feel it corrupts
my brain every time I have to deal with it (needle or haystack first?
anyone?)...
Conclusion
I find BTRFS utterly confusing and I'm worried about its
reliability. I think a lot of work is needed on usability and
coherence before I even consider running this anywhere else than a
lab, and that's really too bad, because there are really nice features
in BTRFS that would greatly help my workflow. (I want to use
filesystem snapshots as high-performance, high frequency backups.)
So now I'm experimenting with OpenZFS. It's so much simpler, just
works, and it's rock solid. After this 8 minute read, I had a
good understanding of how ZFS worked. Here's the 30 seconds overview:
vdev: a RAID array
vpool: a volume group of vdevs
datasets: normal filesystems (or block device, if you want to use
another filesystem on top of ZFS)
There's also other special volumes like caches and logs that
you can (really easily, compared to LVM caching) use to tweak your
setup. You might also want to look at recordsize or ashift
to tweak the filesystem to fit better your workload (or deal with
drives lying about their sector size, I'm looking at you Samsung), but
that's it.
Running ZFS on Linux currently involves building kernel modules from
scratch on every host, which I think is pretty bad. But I was able to
setup a ZFS-only server using this excellent documentation
without too much problem.
I'm hoping some day the copyright issues are resolved and we can at
least ship binary packages, but the politics (e.g. convincing Debian
that is the right thing to do) and the logistics (e.g. DKMS
auto-builders? is that even a thing? how about signed DKMS packages?
fun-fun-fun!) seem really impractical. Who knows, maybe hell will
freeze over (again) and Oracle will fix the CDDL. I
personally think that we should just completely ignore this
problem (which wasn't even supposed to be a problem) and ship
binary packages directly, but I'm a pragmatic and do not always fit
well with the free software fundamentalists.
All of this to say that, short term, we don't have a reliable,
advanced filesystem/logical disk manager in Linux. And that's really
too bad.
Here s my (thirty-first) monthly but brief update about the activities I ve done in the F/L/OSS world.
Debian
This was my 40th month of actively contributing to Debian.
I became a DM in late March 2019 and a DD on Christmas 19! \o/
There s a bunch of things I did this month but mostly non-technical, now that DC22 is around the corner. Here are the things I did:
Debian Uploads
Helped Andrius w/ FTBFS for php-text-captcha, reported via #977403.
I fixed the samed in Ubuntu a couple of months ago and they copied over the patch here.
Other $things:
Volunteering for DC22 Content team.
Leading the Bursary team w/ Paulo.
Answering a bunch of questions of referees and attendees around bursary.
Ubuntu
This was my 15th month of actively contributing to Ubuntu.
Now that I joined Canonical to work on Ubuntu full-time, there s a bunch of things I do! \o/
I mostly worked on different things, I guess.
I was too lazy to maintain a list of things I worked on so there s
no concrete list atm. Maybe I ll get back to this section later or
will start to list stuff from the fall, as I was doing before. :D
Debian (E)LTS
Debian Long Term Support (LTS) is a project to extend the lifetime of all Debian stable releases to (at least) 5 years. Debian LTS is not handled by the Debian security team, but by a separate group of volunteers and companies interested in making it a success.
And Debian Extended LTS (ELTS) is its sister project, extending support to the Jessie release (+2 years after LTS support).
This was my thirty-first month as a Debian LTS and twentieth month as a Debian ELTS paid contributor.
I worked for 23.25 hours for LTS and 20.00 hours for ELTS.
LTS CVE Fixes and Announcements:
Issued DLA 2976-1, fixing CVE-2022-1271, for gzip.
For Debian 9 stretch, these problems have been fixed in version 1.6-5+deb9u1.
Issued DLA 2977-1, fixing CVE-2022-1271, for xz-utils.
For Debian 9 stretch, these problems have been fixed in version 5.2.2-1.2+deb9u1.
Working on src:tiff and src:mbedtls to fix the issues, still waiting for more issues to be reported, though.
Looking at src:mutt CVEs. Haven t had the time to complete but shall roll out next month.
ELTS CVE Fixes and Announcements:
Issued ELA 593-1, fixing CVE-2022-1271, for gzip.
For Debian 8 jessie, these problems have been fixed in version 1.6-4+deb8u1.
Issued ELA 594-1, fixing CVE-2022-1271, for xz-utils.
For Debian 8 jessie, these problems have been fixed in version 5.1.1alpha+20120614-2+deb8u1.
Working on src:tiff and src:beep to fix the issues, still waiting for more issues to be reported for src:tiff and src:beep is a bit of a PITA, though. :)
Finally, TIL, what can all be the reason for systemd services to hang indefinitely. The internet is flooded with numerous reports on this topic but no clear answers. So no more uselessly marked workarounds like: systemctl daemon-reload and systemctl-daemon-reexec for this scenario.
The scene would be something along the lines of:
The snapper-timeline service is important to me and it not running for months is a complete failure. Disappointingly, commands like systemctl --failed do not report of this oddity. The overall system status is reported to be fine, which is completely incorrect.
Thankfully, a kind soul s comment gave the hint. The problem is that you could be having certain services in Activating status, which thus blocks all other services; quietly. So much for the unnecessary fun.
Looking further, in my case, it was:
That was it. I knew the systemd-timesyncd service, in the past, had given me enough headaches. And so was it this time, just quietly doing it all again.
rrs@priyasi:~$ systemctl status systemd-time-wait-sync.service
systemd-time-wait-sync.service - Wait Until Kernel Time Synchronized
Loaded: loaded (/lib/systemd/system/systemd-time-wait-sync.service; enabled; vendor preset>
Active: activating (start) since Fri 2022-04-22 13:14:25 IST; 1min 38s ago
Docs: man:systemd-time-wait-sync.service(8) Main PID: 11090(systemd-time-wa) Tasks: 1(limit: 37051) Memory: 836.0K
CPU: 7ms
CGroup: /system.slice/systemd-time-wait-sync.service
11090 /lib/systemd/systemd-time-wait-sync
Apr 22 13:14:25 priyasi systemd[1]: Starting Wait Until Kernel Time Synchronized...
Apr 22 13:14:25 priyasi systemd-time-wait-sync[11090]: adjtime state 5 status 40 time Fri 2022->
13:16 => 3
Dear LazyWeb, anybody knows of why the systemd-time-wait-sync service would hang indefinitely? I ve had identical setups on many machines, in the same network, where others don t exhibit this problem.
The TimeoutStartSec=infinity is definitely an attribute that shouldn t be shipped in any system services. There are use cases for it but that should be left for local admins to explicitly decide. Hanging for infinity is not a desired behavior for a system service.
In figuring all this out, today I learnt the handy systemctl list-jobs command, which will give the list of active running/blocked/waiting jobs.
(The below was written by Rob Pike, copied here for posterity from The Wayback Machine)
Long ago, as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier. I m not sure but I believe .. went in during the Version 2 rewrite, when the file system became hierarchical (it had a very different structure early on). When one typed ls, however, these files appeared, so either Ken or Dennis added a simple test to the program. It was in assembler then, but the code in question was equivalent to something like this:
if (name[0] == '.') continue;
This statement was a little shorter than what it should have been, which is
if (strcmp(name, ".") == 0 strcmp(name, "..") == 0) continue;
but hey, it was easy.
Two things resulted.
First, a bad precedent was set. A lot of other lazy programmers introduced bugs by making the same simplification. Actual files beginning with periods are often skipped when they should be counted.
Second, and much worse, the idea of a hidden or dot file was created. As a consequence, more lazy programmers started dropping files into everyone s home directory. I don t have all that much stuff installed on the machine I m using to type this, but my home directory has about a hundred dot files and I don t even know what most of them are or whether they re still needed. Every file name evaluation that goes through my home directory is slowed down by this accumulated sludge.
I m pretty sure the concept of a hidden file was an unintended consequence. It was certainly a mistake.
How many bugs and wasted CPU cycles and instances of human frustration (not to mention bad design) have resulted from that one small shortcut about 40 years ago?
Keep that in mind next time you want to cut a corner in your code.
(For those who object that dot files serve a purpose, I don t dispute that but counter that it s the files that serve the purpose, not the convention for their names. They could just as easily be in $HOME/cfg or $HOME/lib, which is what we did in Plan 9, which had no dot files. Lessons can be learned.)
For various obscure reasons, I have a mirror of Debian in one room and the main laptop and so on I use in another. The mirror is connected to a fast Internet line - and has a 1Gb Ethernet cable into the back directly from the router, the laptop and everything else - not so much, everything is wired, but depends on a WiFi link across the property. One end is fast - one end runs like a snail.Steve suggested I use a different tool to make images directly on the mirror machine - jigit. Slightly less polished than jigdo but - if you're on the same machine - blazingly fast. I just used it to make the Blu-Ray sized .iso and was very pleasantly surprised. jigit-mkimage -j [jigdo file] -t [template file] -m Debian=[path to mirror of Debian] -o [output filename] Another nice surprise for me - I have a horrible old Lenovo Ideapad. It's one of the Bay Trail Intel machines with a 32 bit UEFI and a 64 bit processor. I rescued it from the junk heap. Reinstalling it with an image today fixed an issue I had with slow boot and has turned it into an adequate machine for web browsing.All in all, I've done relatively few tests so far - but it's been a good day, as ever.More later.
Shell? Rust!
Not the first shell script I took and made a rust version of, but
probably my largest yet. This time I took my little tm (tmux
helper) tool which is (well, was) a
bit more than 600 lines of shell, and converted it to
Rust.
I got most of the functionality done now, only one major part is
missing.
What s tm?
tm started as a tiny shell script to make handling
tmux easier. The first commit in
git was in July 2013, but I started writing and using it in 2011. It
started out as a kind-of wrapper around ssh, opening tmux windows with
an ssh session on some other hosts. It quickly gained support to open
multiple ssh sessions in one window, telling tmux to synchronize input
(send input to all targets at once), which is great when you have a
set of machines that ought to get the same commands.
tm vs clusterssh / mussh
In spirit it is similar to clusterssh or mussh, allowing to run the
same command on many hosts at the same time. clusterssh sets out to
open new terminals (xterm) per host and gives you an input line, that
it sends everywhere. mussh appears to take your command and then send
it to all the hosts. Both have disadvantages in my opinion: clusterssh
opens lots of xterm windows, and you can not easily switch between
multiple sessions, mussh just seems to send things over ssh and be
done.
tm instead just creates a tmux session, telling it to ssh to the
targets, possibly setting the tmux option to send input to all panes.
And leaves all the rest of the handling to tmux. So you can
detach a session and reattach later easily,
use tmux great builtin support for copy/paste,
see all output, modify things even for one machine only,
zoom in to one machine that needs just ONE bit different (cssh can
do this too),
let colleagues also connect to your tmux session, when needed,
easily add more machines to the mix, if needed,
and all the other extra features tmux brings.
More tm
tm also supports just attaching to existing sessions as well as
killing sessions, mostly for lazyness (less to type than using tmux
directly).
At some point tm gained support for setting up sessions according to
some session file . It knows two formats now, one is simple and
mostly a list of hostnames to open synchronized sessions for. This may
contain LIST commands, which let tm execute that command, expected
output is list of hostnames (or more LIST commands) for the session.
That, combined with the replacement part, lets us have one config file
that opens a set of VMs based on tags our
Ganeti runs, based on tags. It is simply a LIST
command asking for VMs tagged with the replacement arg and up. Very
handy. Or also all VMs on host X .
The second format is basically free form tmux commands . Mostly
commandline tmux call, just drop the tmux in front collection.
Both of them supporting a crude variable replacement.
Conversion to Rust
Some while ago I started playing with Rust and it somehow clicked , I
do like it. My local git tells me, that I tried starting off with
go in 2017, but that appearently did not work out.
Fun, everywhere I can read says that Rust ought to be harder to learn.
So by now I have most of the functionality implemented in the Rust
version, even if I am sure that the code isn t a good Rust example.
I m learning, after all, and already have adjusted big parts of it,
multiple times, whenever I learn (and understand) something more - and
am also sure that this will happen again
Compatibility with old tm
It turns out that my goal of staying compatible with the behaviour of
the old shell script does make some things rather complicated. For
example, the LIST commands in session config files - in shell I just
execute them commands, and shell deals with variable/parameter
expansion, I just set IFS to newline only and read in what I get
back. Simple. Because shell is doing a lot of things for me.
Now, in Rust, it is a different thing at all:
Properly splitting the line into shell words, taking care of quoting
(can t simply take whitespace) (there is shlex)
Expanding specials like ~ and $HOME (there is
home_dir).
Supporting environment variables in general, tm has some that adjust
behaviour of it. Which shell can use globally. Used
lazy_static for a
similar effect - they aren t going to change at runtime ever,
anyways.
Properly supporting the commandline arguments also turned out to be a
bit more work. Rust appearently has multiple crates supporting this, I
settled on clap, but as tm
supports getopts -style as well as free-form arguments (subcommands
in clap), it takes a bit to get that interpreted right.
Speed
Most of the time entirely unimportant in the tool that tm is (open a
tmux with one to some ssh connections to some places is not exactly
hard or time consuming), there are situations, where one can notice
that it s calling out to tmux over and over again, for every single
bit to do, and that just takes time: Configurations that open sessions
to 20 and more hosts at the same time especially lag in setup time.
(My largest setup goes to 443 panes in one window). The compiled Rust
version is so much faster there, it s just great. Nice side effect,
that is. And yes, in the end it is also only driving tmux, still, it
takes less than half the time to do so.
Code, Fun parts
As this is still me learning to write Rust, I am sure the code has
lots to improve. Some of which I will sure find on my own, but if you
have time, I love PRs (or just mails with hints).
Github
Also the first time I used Github Actions to see how it goes. Letting
it build, test, run
clippy and also run a code
coverage tool (Yay, more than
50% covered ) on it. Unsure my tests are good, I am not used to
writing tests for code, but hey, coverage!
Up next
I do have to implement the last missing feature, which is reading the
other config file format. A little scared, as that means somehow
translating those lines into correct calls within the
tmux_interface
I am using, not sure that is easy. I could be bad and just shell
out to tmux on it all the time, but somehow I don t like the thought
of doing that. Maybe (ab)using the control mode, but then, why would I
use tmux_interface, so trying to handle it with that first.
Afterwards I want to gain a new command, to save existing sessions and
be able to recreate them easily. Shouldn t be too hard, tmux has a way
to get at that info, somewhere.
Here s my (twenty-ninth) monthly but brief update about the activities I ve done in the F/L/OSS world.
Debian
This was my 38th month of actively contributing to Debian.
I became a DM in late March 2019 and a DD on Christmas 19! \o/
I had been sick this month, so most of the time I spent away from system, recovering, et al,
and also went through the huge backlog that I had, which is starting to get smaller. :D
Anyway, I did the following stuff in Debian:
Uploads and bug fixes:
at (3.4.4-1) - Adding a DEP8 test for the package, fixing bug #985421.
Other $things:
Mentoring for newcomers.
Moderation of -project mailing list.
Ubuntu
This was my 13th month of actively contributing to Ubuntu.
Now that I joined Canonical to work on Ubuntu full-time, there s a bunch of things I do! \o/
I mostly worked on different things, I guess.
I was too lazy to maintain a list of things I worked on so there s
no concrete list atm. Maybe I ll get back to this section later or
will start to list stuff from the fall, as I was doing before. :D
Debian (E)LTS
Debian Long Term Support (LTS) is a project to extend the lifetime of all Debian stable releases to (at least) 5 years. Debian LTS is not handled by the Debian security team, but by a separate group of volunteers and companies interested in making it a success.
And Debian Extended LTS (ELTS) is its sister project, extending support to the Jessie release (+2 years after LTS support).
This was my twenty-ninth month as a Debian LTS and eighteenth month as a Debian ELTS paid contributor.
Whilst I was assigned 42.75 hours for LTS and 45.25 hours for ELTS, I could only work a little due to being sick and so
I spent 15.75 hours on LTS and 9.25 hours on ELTS and worked on the following things:
LTS CVE Fixes and Announcements:
Issued DLA 2909-1, fixing CVE-2021-45079, for strongswan.
For Debian 9 stretch, these problems have been fixed in version 5.5.1-4+deb9u6.
John Grisham The King of Torts
Lots of things have been happening and I have been unable to be on top of things. There are so many things that happen and keep on happening and a lot of it is just not in control. For those who are watching Brexit, India is going through the same/similar phenomena just without Brexit. I would not like to delve much into Indian happenings as there is no sweet story to tell.
Mum is in hospital (diabetic foot) so a lot of time to read books. So I have been making use of the time and at the same time learning or making connections from what I know of the history of the world which goes on enriching what I read all the time. For e.g. in this book, opens up with people who are on Crack. Now while the book is set in 2003, it is still relevant today for a lot of things. There have been rumors and whatnot that the President of the United States, Ronald Reagan supplied a lot of cocaine to black folks in the early 1980s. While that has never been proved, it has been proved somewhat that the CIA and even people in the state department were part of providing crack cocaine to African Americans (as they refer to blacks) in those days. Whether this was because of black power rising or non-profits like ACLU or other organizations is beyond me. I had also read that the GOP (Republicans/Grand Old Party) in the 1970s itself when computers became fast and could do a lot of processing, came to know if education would be as it is, then soon they would no voters. hence they decided to defund education in America, the end result being massive education loans to prospective students and perhaps partly the reason why China produces more than enough STEM graduates than the total number of Americans who become graduates. It is a shame nonetheless, that education in the U.S. is never top . This is somewhat from a Republican perspective. That is also the reason they are much anti-science.
Tort Cases
India doesn t have either class-action suits or tort cases. But before we go headlong, this is what tort means. The book however is not about general tort cases but medical tort cases. The idea is that medical companies often produce medicines claiming they solve x or y issues but more often than not they take short-cuts to get approval from FDA and other regulators. And sooner or later those medicines can and do have harmful effects on the body, sometimes resulting in death.
One of the more interesting articles that I read and probably also shared is the work done by Mr. Rob Bilott. While it is a typical David and Goliath story once you read the book, you realize that there are and were many difficulties in Mr. Rob s path that are never fully appreciated or even worked out. The biggest issue is the 8 years that he paid out of his own pocket to get the hundreds and thousands of people tested. How many of us would do that?
And this is before proving causation of any disease, illness or anything to a particular environment, pollution etc. is hard even then and even now. Whatever money the victims receive afterward and whatever went to Mr. Rob Bilott would never compensate for the stress faced by him. And lawyers have to be careful, if they ask too little, they are not hurting the company and there is no change in its behavior. If they ask too much, the company can declare Chapter 11, bankruptcy so they have to keep the balance.
There is also a lot of greed shown by the tort lawyer and while at the end he does tell about a company s nefarious activities that he suspects he could share his opinion only after giving up his law career. There is and was talk of tort-reform in the book but as can be seen if you reform tort there is just no way to punish such companies but that is in the U.S.
There is also some observations that I have shared over the years, for e.g. Europe bans far more drugs than the U.S. does. A major part of it is perhaps due to the fact that Europe has 26/27 independent medical regulators and one country bans medicine for one or the other reason, the rest of Europe also bans the same. In the U.S. it is only the FDA. I have read they have had both funding and staffing issues for years and this is from before the pandemic. The Indian regulators are much worse. One could follow Priyanka Pulla s articles in Mint and others where she has shared how the regulator is corrupt and lazy and a combo of both.
And all of this is besides how doctors are corrupted in India by marketing executives of pharma companies. That would be a whole article in itself. In short, when you read this book, there are so many thoughts that come alive when you are reading the book. The sad part is the book doesn t offer any solutions at all. John Grisham s books are usually legal thrillers and courtroom exchanges, this one though is and was very different. This one sadly doesn t take one to any conclusion apart from the fact that we live in an imperfect world and there don t seem to be any solutions. This was even shared by Rep. Katie Porter in her pinned tweet. The Abbvie s of the world will continue to take common people like you and me for a ride.
Review: The Story of the Treasure Seekers, by E. Nesbit
Publisher:
Amazon
Copyright:
1899
Printing:
May 2012
ASIN:
B0082ZBXSI
Format:
Kindle
Pages:
136
The Story of the Treasure Seekers was originally published in 1899
and is no longer covered by copyright. I read the free Amazon Kindle
version because it was convenient. My guess is that Amazon is
republishing the Project
Gutenberg version, but they only credit "a community of volunteers."
There are six Bastable children: Dora, Oswald, Dicky, the twins Alice and
Noel, and Horace Octavius (H.O.), the youngest. Their mother is dead and
the family's finances have suffered in the wake of her death (or, as the
first-person narrator puts it, "the fortunes of the ancient House of
Bastable were really fallen"), which means that their father works long
hours and is very absorbed with his business. That leaves the six kids
largely to fend for themselves, since they can't afford school. Clearly
the solution is to find treasure.
This is a fix-up novel constructed from short stories that were originally
published in various periodicals, reordered and occasionally rewritten for
the collected publication. To be honest, calling it a fix-up novel is
generous; there are some references to previous events, but the first
fourteen chapters can mostly stand alone. The last two chapters are
closely related and provide an ending. More on that in a moment.
What grabs the reader's attention from the first paragraph is the writing
style:
This is the story of the different ways we looked for treasure, and I
think when you have read it you will see that we were not lazy about
the looking.
There are some things I must tell before I begin to tell about the
treasure-seeking, because I have read books myself, and I know how
beastly it is when a story begins, "Alas!" said Hildegarde with a deep
sigh, "we must look our last on this ancestral home" and then some
one else says something and you don't know for pages and pages where
the home is, or who Hildegarde is, or anything about it.
The first-person narrator of The Story of the Treasure Seekers is
one of the six kids.
It is one of us that tells this story but I shall not tell you
which: only at the very end perhaps I will.
The narrator then goes on to elaborately praise one of the kids,
occasionally accidentally uses "I" instead of their name, and then
remembers and tries to hide who is telling the story again. It's
beautifully done and had me snickering throughout the book. It's not much
of a mystery (you will figure out who is telling the story very quickly),
but Nesbit captures the writing style of a kid astonishingly well without
making the story poorly written. Descriptions of events have a headlong
style that captures a child's sense of adventure and heedless immortality
mixed with quiet observations that remind the reader that kids don't miss
as much as people think they do.
I think the most skillful part of this book is the way Nesbit captures a
kid's disregard of literary convention. The narrator in a book written by
an adult tends to fit into a standard choice of story-telling style and
follow it consistently. Even first-person narrators who break some of
those rules feel like intentionally constructed characters. The
Story of the Treasure Seekers is instead half "kid telling a story" and
half "kid trying to emulate the way stories are told in books" and tends
to veer wildly between the two when the narrator gets excited, as if
they're vaguely aware of the conventions they're supposed to be following
but are murky on the specifics. It feels exactly like the sort of book a
smart and well-read kid would write (with extensive help from an editor).
The other thing that Nesbit handles exceptionally well is the dynamic
between the six kids. This is a collection of fairly short stories, so
there isn't a lot of room for characterization. The kids are mostly
sketched out with one or two memorable quirks. But Nesbit puts a lot of
effort into the dynamics that arise between the children in a tight-knit
family, properly making the group of kids as a whole and in various
combinations a sort of character in their own right. Never for a moment
does either the reader or the kids forget that they have siblings. Most
adventures involve some process of sorting out who is going to come along
and who is going to do other things, and there's a constant but
unobtrusive background rhythm of bickering, making up, supporting each
other, being frustrated by each other, and getting exasperated at each
other's quirks. It's one of the better-written sibling dynamics that I've
read.
I somehow managed to miss Nesbit entirely as a kid, probably because she
didn't write long series and child me was strongly biased towards books
that were part of long series. (One book was at most a pleasant few
hours; there needed to be a whole series attached to get any reasonable
amount of reading out of the world.) This was nonetheless a fun bit of
nostalgia because it was so much like the books I did read: kids finding
adventures and making things up, getting into various trouble but getting
out of it by being honest and kind, and only occasional and spotty adult
supervision. Reading as an adult, I can see the touches of melancholy of
loss that Nesbit embeds into this quest for riches, but part of the appeal
of the stories is that the kids determinedly refuse to talk about it
except as a problem to be solved.
Nesbit was a rather famous progressive, but this is still a book of its
time, which means there's one instance of the n-word and the kids have
grown up playing the very racist version of cowboys and indians. The
narrator also does a lot of stereotyping of boys and girls, although
Nesbit undermines that a bit by making Alice a tomboy. I found all of
this easier to ignore because the story is narrated by one of the kids who
doesn't know any better, but your mileage may vary.
I am always entertained by how anyone worth writing about in a British
children's novel of this era has servants. You know the Bastables have
fallen upon hard times because they only have one servant. The kids don't
have much respect for Eliza, which I found a bit off-putting, and I
wondered what this world looks like from her perspective. She clearly did
a lot of the work of raising these motherless kids, but the kids view her
as the hired help or an obstacle to be avoided, and there's not a lot of
gratitude present.
As the stories unfold, it becomes more and more clear that there's a quiet
conspiracy of surrounding adults to watch out for these kids, which the
kids never notice. This says good things about society, but it does
undermine the adventures a little, and by the end of the book the sameness
of the stories was wearing a bit thin. The high point of the book is
probably chapter eight, in which the kids make their own newspaper, the
entirety of which is reproduced in the book and is a note-perfect
recreation of what an enterprising group of kids would come up with.
In the last two stories, Nesbit tacks on an ending that was probably
obligatory, but which I thought undermined some of the emotional subtext
of the rest of the book. I'm not sure how else one could have put an
ending on this book, but the ending she chose emphasized the degree to
which the adventures really were just play, and the kids are rewarded in
these stories for their ethics and their circumstances rather than for
anything they concretely do. It's a bit unsatisfying.
This is mostly a nostalgia read, but I'm glad I read it. If this book was
not part of your childhood, it's worth reading if only for how well Nesbit
captures a child's narrative voice.
Rating: 7 out of 10
Review: I Didn't Do the Thing Today, by Madeleine Dore
Publisher:
Avery
Copyright:
2022
ISBN:
0-593-41914-6
Format:
Kindle
Pages:
291
At least from my narrow view of it, the world of productivity self-help
literature is a fascinating place right now. The pandemic overturned
normal work patterns and exacerbated schedule inequality, creating vastly
different experiences for the people whose work continued to be in-person
and the people whose work could become mostly or entirely remote.
Self-help literature, which is primarily aimed at the more affluent
white-collar class, primarily tracked the latter disruption: newly-remote
work, endless Zoom meetings, the impossibility of child care, the
breakdown of boundaries between work and home, and the dawning realization
that much of the mechanics of day-to-day office work are neither
productive nor defensible.
My primary exposure these days to the more traditional self-help
productivity literature is via Cal Newport.
The stereotype of the productivity self-help book is a collection of life
hacks and list-making techniques that will help you become a more
efficient capitalist cog, but Newport has been moving away from that dead
end for as long as I've been reading him, and his
recent work focuses more on structural issues
with the organization of knowledge work. He also shares with the newer
productivity writers a willingness to tell people to use the free time
they recover via improved efficiency on some life goal other than improved
job productivity. But he's still prickly and defensive about the
importance of personal productivity and accomplishing things. He gives
lip service on his podcast to the value of the critique of productivity,
but then usually reverts to characterizing anti-productivity arguments as
saying that productivity is a capitalist invention to control workers.
(Someone has doubtless said this on Twitter, but I've never seen a serious
critique of productivity make this simplistic of an argument.)
On the anti-productivity side, as it's commonly called, I've seen a lot of
new writing in the past couple of years that tries to break the connection
between productivity and human worth so endemic to US society. This is
not a new analysis; disabled writers have been making this point for
decades, it's present in both Keynes and in Galbraith's
The Affluent Society, and Kathi Weeks's
The Problem with Work traces some of its
history in Marxist thought. But what does feel new to me is its
widespread mainstream appearance in newspaper articles, viral blog posts,
and books such as Jenny Odell's How to Do Nothing and Devon Price's
Laziness Does Not Exist. The pushback
against defining life around productivity is having a moment.
Entering this discussion is Madeleine Dore's I Didn't Do the Thing
Today. Dore is the author of the
Extraordinary Routines blog and
host of the Routines and
Ruts podcast. Extraordinary Routines began as a survey of how various
people organize their daily lives. I Didn't Do the Thing Today is,
according to the preface, a summary of the thoughts Dore has had about her
own life and routines as a result of those interviews.
As you might guess from the subtitle (Letting Go of Productivity
Guilt), Dore's book is superficially on the anti-productivity side. Its
chapters are organized around gentle critiques of productivity concepts,
with titles like "The Hopeless Search for the Ideal Routine," "The Myth of
Balance," or "The Harsh Rules of Discipline." But I think
anti-productivity is a poor name for this critique; its writers are not
opposed to being productive, only to its position as an all-consuming
focus and guilt-generating measure of personal worth.
Dore structures most chapters by naming an aspect, goal, or concern of a
life defined by productivity, such as wasted time, ambition, busyness,
distraction, comparison, or indecision. Each chapter sketches the impact
of that idea and then attempts to gently dismantle the grip that it may
have on the reader's life. All of these discussions are nuanced; it's
rare for Dore to say that one of these aspects has no value, and she
anticipates numerous objections. But her overarching goal is to help the
reader be more comfortable with imperfection, more willing to live in the
moment, and less frustrated with the limitations of life and the human
brain. If striving for productivity is like lifting weights, Dore's
diagnosis is that we've tried too hard for too long, and have overworked
that muscle until it is cramping. This book is a gentle massage to induce
the muscle to relax and let go.
Whether this will work is, as with all self-help books, individual. I
found it was best read in small quantities, perhaps a chapter per day,
since it otherwise began feeling too much the same. I'm also not the
ideal audience; Dore is a creative freelancer and primarily interviewed
other creative people, which I think has a different sort of productivity
rhythm than the work that I do. She's also not a planner to the degree
that I am; more on that below. And yet, I found this book worked on me
anyway. I can't say that I was captivated all the way through, but I
found myself mentally relaxing while I was reading it, and I may re-read
some chapters from time to time.
How does this relate to the genre of productivity self-help? With less
conflict than I think productivity writers believe, although there seems
to be one foundational difference of perspective.
Dore is not opposed to accomplishing things, or even to systems that help
people accomplish things. She is more attuned than the typical
productivity writer to the guilt and frustration that can accumulate when
one has a day in which one does not do the thing, but her goal is not to
talk you out of attempting things. It is, instead, to convince you to
hold those attempts and goals more lightly, to allow them to move and
shift and change, and to not treat a failure to do the thing today as a
reason for guilt. This is wholly compatible with standard productivity
advice. It's adding nuance at one level of abstraction higher: how
tightly to cling to productivity goals, and what to do when they don't
work out. Cramping muscles are not strong muscles capable of lifting
heavy things. If one can massage out the cramp, one's productivity by
even the strict economic definition may improve.
Where I do see a conflict is that most productivity writers are planners,
and Dore is not. This is, I think, a significant blind spot in
productivity self-help writing. Cal Newport, for example, advocates
time-block planning, where every hour of the working day has a job.
David Allen advocates a complex set of
comprehensive lists and well-defined next actions.
Mark Forster builds a flurry of small systems
for working through lists. The standard in productivity writing is to to
add structure to your day and cultivate the self-discipline required to
stick to that structure.
For many people, including me, this largely works. I'm mostly a planner,
and when my life gets chaotic, adding more structure and focusing on that
structure helps me. But the productivity writers I've read are quite
insistent that their style of structure will work for everyone, and on
that point I am dubious. Newport, for example, advocates time-block
planning for everyone without exception, insisting that it is the best way
to structure a day. Dore, in contrast, describes spending years trying to
perfect a routine before realizing that elastic possibilities work better
for her than routines. For those who are more like Dore than Newport,
I Didn't Do the Thing Today is more likely to be helpful than
Newport's instructions. This doesn't make Newport's ideas wrong; it
simply makes them not universal, something that the productivity self-help
genre seems to have trouble acknowledging.
Even for readers like myself who prefer structure, I Didn't Do the
Thing Today is a valuable corrective to the emphasis on every-better
systems. For those who never got along with too much structure, I think
it may strike a chord. The standard self-help caveat still applies: Dore
has the most to say to people who are in a similar social class and line
of work as her. I'm not sure this book will be of much help to someone
who has to juggle two jobs with shift work and child care, where the
problem is more sharp external constraints than internalized productivity
guilt. But for its target audience, I think it's a valuable, calming
message. Dore doesn't have a recipe to sort out your life, but may help
you feel better about the merits of life unsorted.
Rating: 7 out of 10
Here s my (twenty-seventh) monthly but brief update about the activities I ve done in the F/L/OSS world.
Debian
This was my 36th month of actively contributing to Debian.
I became a DM in late March 2019 and a DD on Christmas 19! \o/
Just churning through the backlog again this month. Ugh.
Anyway, I did the following stuff in Debian:
Uploads and bug fixes:
ruby2.7 (2.7.5-1) - New upstream version fixing 3 new CVEs.
Other $things:
Mentoring for newcomers.
Moderation of -project mailing list.
Ubuntu
This was my 11th month of actively contributing to Ubuntu.
Now that I ve joined Canonical to work on Ubuntu full-time, there s a bunch of things I do! \o/
I mostly worked on different things, I guess.
I was too lazy to maintain a list of things I worked on so there s
no concrete list atm. Maybe I ll get back to this section later or
will start to list stuff from next year onward, as I was doing before. :D
Debian (E)LTS
Debian Long Term Support (LTS) is a project to extend the lifetime of all Debian stable releases to (at least) 5 years. Debian LTS is not handled by the Debian security team, but by a separate group of volunteers and companies interested in making it a success.
And Debian Extended LTS (ELTS) is its sister project, extending support to the Jessie release (+2 years after LTS support).
This was my twenty-seventh month as a Debian LTS and eighteenth month as a Debian ELTS paid contributor.
I was assigned 40.00 hours for LTS and 60.00 hours for ELTS and worked on the following things:
(since I had a 3-week vacation, I wanted to wrap things up that were pending and so I worked for 20h more for LTS, which I ll compensate the next month!)
Issued DLA 2854-1, fixing CVE-2017-18635, for novnc.
For Debian 9 stretch, these problems have been fixed in version 1:0.4+dfsg+1+20131010+gitf68af8af3d-6+deb9u1.
Issued ELA 536-1, fixing CVE-2021-43818, for lxml.
For Debian 8 jessie, these problems have been fixed in version Prior to version 4.6.5, the HTML Cleaner in lxml.html lets certain.
Started working on src:samba for CVE-2020-25717 to CVE-2020-25722 and CVE-2021-23192 for jessie and stretch, both.
The version difference b/w the suites are a bit too much for the patch(es) to be easily backported. I ve talked to Anton to work something out. \o/
Found the problem w/ libjdom1-java. Will have to roll the regression upload.
I ve prepared the patch but needs some testing to be finally rolled out. Same for stretch.
Other (E)LTS Work:
Front-desk duty from 29-11 to 05-12 and 20-12 to 26-12 for both LTS and ELTS.
Advent of Code, for those not in the know,
is a yearly Advent calendar (since 2015) of coding puzzles many people
participate in for a plenary of reasons ranging from speed coding to code
golf with stops at learning a new language or practicing already known
ones.
I usually write boring C++, but any language and then some can be used.
There are reports of people implementing it in hardware, solving them by
hand on paper or using Microsoft Excel
so, after solving a puzzle the easy way yesterday, this time
I thought: CHALLENGE ACCEPTED! as I somehow remembered an old 2008
article about solving Sudoku with aptitude
(Daniel Burrows via archive.org as the blog is long gone)
and the good same old a package management system that can solve [puzzles] based on package dependency rules is not something that I think would be useful or worth having (Russell Coker).
Day 8 has a rather lengthy
problem description and can reasonably be approached in a bunch of
different way. One unreasonable approach might be to massage the
problem description into Debian packages and let apt help me solve the
problem (specifically Part 2, which you unlock by solving Part 1. You
can do that now, I will wait here.)
Be warned: I am spoiling Part 2 in the following, so solve it yourself
first if you are interested.
I will try to be reasonable consistent in naming things in the following
and so have chosen: The input we get are lines like acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab cdfeb fcadb cdfeb cdbaf.
The letters are wires mixed up and connected to the segments of the
displays: A group of these letters is hence a digit (the first 10)
which represent one of the digits 0 to 9 and (after the pipe) the four
displays which match (after sorting) one of the digits which means
this display shows this digit. We are interested in which digits are
displayed to solve the puzzle. To help us we also know which segments
form which digit, we just don't know the wiring in the back.
So we should identify which wire maps to which segment!
We are introducing the packages wire-X-connects-to-Y for this which
each provide & conflict1 with the virtual packages segment-Y and
wire-X-connects.
The later ensures that for a given wire we can only pick one segment and
the former ensures that not multiple wires map onto the same segment.
As an example: wire a's possible association with segment b is
described as:
Note that we do not know if this is true! We generate packages for
all possible (and then some) combinations and hope dependency resolution
will solve the problem for us. So don't worry, the hard part will be
done by apt, we just have to provide all (im)possibilities!
What we need now is to translate the 10 digits (and 4 outputs) from
something like acedgfb into digit-0-is-eight and not, say
digit-0-is-one. A clever solution might realize that a one consists
only of two segments so a digit wiring up seven segments can not be
a 1 (and must be 8 instead), but again we aren't here to be clever:
We want apt to figure that out for us! So what we do is simply making
every digit-0-is-N (im)possible choice available as a package and
apply constraints: A given digit-N can only display one number and
each N is unique as digit so for both we deploy Provides
& Conflicts again.
We also need to reason about the segments in the digits: Each of the
digit packages gets Depends on wire-X-connects-to-Y where X is each
possible wire (e.g. acedgfb) and Y each segment forming the digit
(e.g. cf for one). The different choices for X are or'ed together,
so that either of them satisfies the Y.
We know something else too through: The segments which are not used by
the digit can not be wired to any of the Xs. We model this with
Conflicts on wire-X-connects-to-Y.
As an example: If digit-0s acedgfb would be displaying a one
(remember, it can't) the following package would be installable:
Repeat such stanzas for all 10 possible digits for digit-0 and then
repeat this for all the other nine digit-N. We produce pretty much the
same stanzas for display-0(-is-one), just that we omit the second
Provides & Conflicts from above (digit-is-one) as in the display
digits can be repeated. The rest is the same (modulo using display
instead of digit as name of course).
Lastly we create a package dubbed solution which depends on all 10
digit-N and 4 display-N all of them virtual packages apt will have
to choose an installable provider from and we are nearly done!
The resulting Packages file2 we can give to apt while requesting to
install the package solution and it will spit out not only the display
values we are interested in but also which number each digit represents
and which wire is connected to which segment. Nifty!
$ ./skip-aoc 'acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab cdfeb fcadb cdfeb cdbaf'
[ ]
The following additional packages will be installed:
digit-0-is-eight digit-1-is-five digit-2-is-two digit-3-is-three
digit-4-is-seven digit-5-is-nine digit-6-is-six digit-7-is-four
digit-8-is-zero digit-9-is-one display-1-is-five display-2-is-three
display-3-is-five display-4-is-three wire-a-connects-to-c
wire-b-connects-to-f wire-c-connects-to-g wire-d-connects-to-a
wire-e-connects-to-b wire-f-connects-to-d wire-g-connects-to-e
[ ]
0 upgraded, 22 newly installed, 0 to remove and 0 not upgraded.
We are only interested in the numbers on the display through, so grepping
the apt output (-V is our friend here) a bit should let us end up with
what we need as calculating3 is (unsurprisingly) not a strong suit of
our package relationship language so we need a few shell commands to
help us with the rest.
$ ./skip-aoc 'acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab cdfeb fcadb cdfeb cdbaf' -qq
5353
I have written the skip-aoc script as a testcase for apt,
so to run it you need to place it in
/path/to/source/of/apt/test/integration and built apt first, but that
is only due to my laziness. We could write a standalone script
interfacing with the system installed apt directly and in any apt
version since
~2011.
To hand in the solution for the puzzle we just need to run this on each
line of the input (~200 lines) and add all numbers together. In other
words: Behold this beautiful shell one-liner:
parallel -I ' ' ./skip-aoc ' ' -qq < input.txt paste -s -d'+' - bc
(You may want to run parallel with -P to properly grill your CPU as
that process can take a while otherwise and it still does anyhow as
I haven't optimized it at all the testing framework does a lot of
pointless things wasting time here, but we aren't aiming for the
leaderboard so )
That might or even likely will fail through as I have so far omitted a
not unimportant detail: The default APT resolver is not able to solve
this puzzle with the given problem description we need another solver!
Thankfully that is as easy as installing apt-cudf (and with it aspcud)
which the script is using via --solver aspcud to make apt hand over the
puzzle to a "proper" solver (or better: A solver who is supposed to be
good at "answering set" questions). The buildds are using this for
experimental and/or backports builds and also for installability checks
via dose3 btw, so you might have encountered it before.
Be careful however: Just because aspcud can solve this puzzle doesn't
mean it is a good default resolver for your day to day apt. One of the
reasons the default resolver has such a hard time solving this here is
that or-groups have usually an order in which the first is preferred over
every later option and so fort. This is of no concern here as all these
alternatives will collapse to a single solution anyhow, but if there are
multiple viable solutions (which is often the case) picking the "wrong"
alternative can have bad consequences. A classic example would be
exim4 postfix nullmailer. They are all MTAs
but behave very different. The non-default solvers also tend to lack
certain features like keeping track of auto-installed packages or
installing Recommends/Suggests. That said, Julian is working on
another solver
as I write this which might deal with more of these issues.
And lastly: I am also relatively sure that with a bit of massaging the
default resolver could be made to understand the problem, but I can't
play all day with this maybe some other day.
Disclaimer: Originally posted in the daily megathread
on reddit, the version here is just slightly better understandable as
I have hopefully renamed all the packages to have more conventional
names and tried to explain what I am actually doing.
No cows were harmed in this improved version, either.
If you would upload those packages somewhere, it would be good
style to add Replaces as well, but it is of minor concern for apt
so I am leaving them out here for readability.
We have generated 49 wires, 100 digits, 40 display and 1 solution
package for a grant total of 190 packages. We are also making use of
a few purely virtual ones, but that doesn't add up to many packages
in total. So few packages are practically childs play for apt given it
usually deals with thousand times more. The instability for those
packages tends to be a lot better through as only 22 of 190 packages
we generated can (and will) be installed. Britney will hate you if
your uploads to Debian unstable are even remotely as bad as this.
What we could do is introduce 10.000 packages which denote every
possible display value from 0000 to 9999. We would then need to
duplicate our 10.190 packages for each line (namespace them) and then
add a bit more than a million packages with the correct dependencies
for summing up the individual packages for apt to be able to display
the final result all by itself. That would take a while through as at
that point we are looking at working with ~22 million packages with
a gazillion amount of dependencies probably overworking every solver
we would throw at it a bit of shell glue seems the better option for
now.
This article was written by David Kalnischkies on apt-get a life and republished here by pulling it from a syndication feed. You should check there for updates and more articles about apt and EDSP.
Welcome to the 34th post in the rambunctiously refreshing R recitations, or R4. Today s post is about architecture.
Mies defined modernism. When still in Europe, I had been to the Neue Nationalgalerie in Berlin which provides a gorgeous space for the arts. Twenty-five years ago, I worked next to his Toronto-Dominion Center in Toronto. Here in Chicago we have numerous buildings: the Federal Center (the Dirksen, the Kluczynski and the US Post Office rounding out the square in the Loop), multiple buildings on the Illinois Tech (aka IIT) Campus where he taught in the architecture department he created and lead, the (formerly called) IBM Plaza building at the river and more.
Structure and minimalism, often based on the same core elements of black steel beams and glass, are a landmark of these buildings. One immediately senses that there is nothing left to take away.
Code and programming can be similar. We too compose based on parts we assemble and combine to create something hopefully larger than the parts. The difficulty arising from too many dependencies is something we discussed before both here in this 2018 post but also via the tinyverse site.
Over the last seven days, and via uploads to new versions to CRAN, I have switched the vignettes of seven packages from using minidown (which in turn requires rmarkdown and knitr, plus their aggregate dependencies) to using simplermarkdown with its sole dependency. That is, of course, a personal choice. I tend to not even knit much in my vignettes (and simplermarkdown supports what I do) but to rely mostly on pandoc for code rendering. So I only need a small subset of the functionality provided, but I can not access just that as the default comes with numerous bells, whistles as well as enough other instruments to form a small marching band.
A picture may express this better:
(courtesy of the deepdep package for the figures).
Which of these two setups is less likely to surprise you with random breaks, say in continuous integration? Which takes less time to install, and burns fewer cpu cycles just to be set up, each time we run a new test? Which is taxing your students, colleagues, collaborators, users, less on setup for use or replication? The first, comprises a total of 29 dependencies, or the second with just one?
My money is on the second choice. Less is more.
One might think, this blog is exclusively about weirdlanguage behavior and yelling at computers Well, welcome to another episode of Jackass!
Today's opponent is Ruby, or maybe minitest , or maybe Mocha. I'm not exactly sure, but it was a rather amusing exercise and I like to share my nightmares ;)
It all started with the classical "you're using old and unmaintained software, please switch to something new".
The first attempt was to switch from the ci_reporter_minitest plugin to the minitest-ci plugin. While the change worked great for Foreman itself, it broke the reporting in Katello - the tests would run but no junit.xml was generated and Jenkins rightfully complained that it got no test results.
While investigating what the hell was wrong, we realized that Katello was already using a minitest reporting plugin: minitest-reporters. Loading two different reporting plugins seemed like a good source for problems, so I tried using the same plugin for Foreman too.
Guess what? After a bit of massaging (mostly to disable the second minitest-reporters initialization in Katello) reporting of test results from Katello started to work like a charm. But now the Foreman tests started to fail. Not fail to report, fail to actually run. WTH
The failure was quite interesting too:
test/unit/parameter_filter_test.rb:5:in block in <class:ParameterFilterTest>':
Mocha methods cannot be used outside the context of a test (Mocha::NotInitializedError)
Yes, this is a single test file failing, all others were fine.
The failing code doesn't look problematic on first glance:
The failing line (5) is mock('Example').tap and for some reason Mocha thinks it's not initialized here.
This certainly has something to do with how the various reporting plugins inject themselves, but I really didn't want to debug how to run two reporting plugins in parallel (which, as you remember, didn't expose this behavior). So the only real path forward was to debug what's happening here.
Calling the test on its own, with one of the working reporter was the first step:
Wait, what? #<Mocha::Mock: >? Shouldn't this read more like ParameterFilterTest:: as it happens for every single other test in our test suite? It definitely should! That's actually great, as it tells us that there is really something wrong with the test and the change of the reporting plugin just makes it worse.
What comes next is sheer luck. Well, that, and years of experience in yelling at computers.
We use let(:klass) to define an object called klass and this object is a Mocha::Mock that we'll use in our tests later. Now klass is a very common term in Ruby when talking about classes and needing to store them mostly because one can't use class which is a keyword. Is something else in the stack using klass and our let is overriding that, making this whole thing explode?
It was! The moment we replaced klass with klass1 (silly, I know, but there also was a klass2 in that code, so it did fit), things started to work nicely.
I really liked Tomer's comment in the PR: "no idea why, but I am not going to dig into mocha to figure that out."
Turns out, I couldn't let (HAH!) the code rest and really wanted to understand what happened there.
What I didn't want to do is to debug the whole Foreman test stack, because it is massive.
So I started to write a minimal reproducer for the issue.
All starts with a Gemfile, as we need a few dependencies:
And a test! I took the liberty to replace ActiveSupport::TestCase with Minitest::Test, as the test won't be using any Rails features and I wanted to keep my environment minimal.
Wait, I didn't change anything and it's already failing?! Fuck! I mean, cool!
But the test isn't minimal yet. What can we reduce? let is just a fancy, lazy def, right? So instead of let(:klass) we should be able to write def class and achieve a similar outcome and drop that Minitest::Spec.
$ bundle exec rake testTESTOPTS=-v
/home/evgeni/Devel/minitest-wtf/test/parameter_filter_test.rb:5:in klass': Mocha methods cannot be used outside the context of a test (Mocha::NotInitializedError) from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/test_unit/reporter.rb:68:in format_line' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/test_unit/reporter.rb:15:in record' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:682:in block in record' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:681:in each' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:681:in record' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:324:in run_one_method' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:311:in block (2 levels) in run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:310:in each' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:310:in block in run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:350:in on_signal' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:337:in with_info_handler' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:309:in run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:159:in block in __run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:159:in map' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:159:in __run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:136:in run' from /home/evgeni/Devel/minitest-wtf/vendor/bundle/ruby/3.0.0/gems/minitest-5.10.3/lib/minitest.rb:63:in block in autorun'rake aborted!
Oh nice, this is even better! Instead of the mangled class name, we now get the very same error the Foreman tests aborted with, plus a nice stack trace! But wait, why is it pointing at railties? We're not loading that! Anyways, lets look at railties-6.1.4.1/lib/rails/test_unit/reporter.rb, line 68
defformat_line(result)klass=result.respond_to?(:klass)?result.klass:result.class"%s#%s = %.2f s = %s"%[klass,result.name,result.time,result.result_code]end
Heh, this is touching result.klass, which we just messed up. Nice!
But quickly back to railties What if we only add that to the Gemfile, not full blown Rails?
Yepp, same failure. Also happens with require => false added to the line, so it seems railties somehow injects itself into rake even if nothing is using it?! "Cool"!
By the way, why are we still pinning minitest to < 5.11? Oh right, this was the original reason to look into that whole topic. And, uh, it's pointing at klass there already! 4 years ago!
So lets remove that boundary and funny enough, now tests are passing again, even if we use klass!
Minitest 5.11 changed how Minitest::Test is structured, and seems not to rely on klass at that point anymore. And I guess Rails also changed a bit since the original pin was put in place four years ago.
I didn't want to go another rabbit hole, finding out what changed in Rails, but I did try with 5.0 (well, 5.0.7.2) to be precise, and the output with newer (>= 5.11) Minitest was interesting:
It's leaking Minitest::Result as klass now, instead of Mocha::Mock. So probably something along these lines was broken 4 years ago and triggered this pin.
What do we learn from that?
klass is cursed and shouldn't be used in places where inheritance and tooling might decide to use it for some reason
inheritance is cursed - why the heck are implementation details of Minitest leaking inside my tests?!
tooling is cursed - why is railties injecting stuff when I didn't ask it to?!
dependency pinning is cursed - at least if you pin to avoid an issue and then forget about said issue for four years